/*
 * Copyright (c) 2018-2999 九五云信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.api.listener;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.app.dto.ShopCartItemDiscountDto;
import com.yami.shop.bean.app.dto.ShopCartItemDto;
import com.yami.shop.bean.app.dto.ShopCartOrderDto;
import com.yami.shop.bean.app.dto.ShopCartOrderMergerDto;
import com.yami.shop.bean.enums.OrderStatus;
import com.yami.shop.bean.enums.OrderType;
import com.yami.shop.bean.event.SubmitOrderEvent;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.order.SubmitOrderOrder;
import com.yami.shop.bean.param.SkuRetailParam;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.i18n.LanguageEnum;
import com.yami.shop.common.util.Arith;
import com.yami.shop.dao.*;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.*;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 确认订单信息时的默认操作
 *
 * @author LGH
 */
@Component("defaultSubmitOrderListener")
@AllArgsConstructor
public class SubmitOrderListener {


    private final MapperFacade mapperFacade;

    private final UserAddrOrderService userAddrOrderService;

    private final ProductService productService;

    private final SkuService skuService;

    private final Snowflake snowflake;

    private final OrderItemMapper orderItemMapper;

    private final SkuMapper skuMapper;

    private final ProductMapper productMapper;

    private final OrderMapper orderMapper;

    private final OrderSettlementMapper orderSettlementMapper;

    private final BasketMapper basketMapper;

    private final SkuRetailService skuRetailService;

    private final SkuRetailMapper skuRetailMapper;

    private final RetailProdMapper retailProdMapper;

    private final OrderRetailProdLogService orderRetailProdLogService;

    /**
     * 计算订单金额
     */
    @EventListener(SubmitOrderEvent.class)
    @Order(SubmitOrderOrder.DEFAULT)
    public void defaultSubmitOrderListener(SubmitOrderEvent event) {
        Date now = new Date();
        String userId = SecurityUtils.getUser().getUserId();

        ShopCartOrderMergerDto mergerOrder = event.getMergerOrder();

        // 订单商品参数
        List<ShopCartOrderDto> shopCartOrders = mergerOrder.getShopCartOrders();

        List<Long> basketIds = new ArrayList<>();
        // 商品skuid为key 需要更新的sku为value的map
        Map<Long, Sku> skuStocksMap = new HashMap<>(16);
        // 商品productid为key 需要更新的product为value的map
        Map<Long, Product> prodStocksMap = new HashMap<>(16);

        List<SkuRetailParam> skuRetailParams = new ArrayList<>();

        if(CollectionUtils.isNotEmpty(shopCartOrders)) {
            // 每个店铺生成一个订单
            for (ShopCartOrderDto shopCartOrderDto : shopCartOrders) {
                Double sumPlatformAmount = 0.0;
                // 使用雪花算法生成的订单号
                String orderNumber = String.valueOf(snowflake.nextId());
                shopCartOrderDto.setOrderNumber(orderNumber);

                Long shopId = shopCartOrderDto.getShopId();


                // 订单商品名称
                StringBuilder orderProdName = new StringBuilder(100);

                // 订单商品中文名称
                StringBuilder orderProdNameCn = new StringBuilder(100);

                // 订单商品英文名称
                StringBuilder orderProdNameEn = new StringBuilder(100);

                List<OrderItem> orderItems = new ArrayList<>();
                Date date = null;
                List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCartOrderDto.getShopCartItemDiscounts();
                for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
                    List<ShopCartItemDto> shopCartItems = shopCartItemDiscount.getShopCartItems();
                    for (ShopCartItemDto shopCartItem : shopCartItems) {
                        // 是否预售商品
                        if(Objects.nonNull(shopCartItem.getPreSellStatus()) &&Objects.equals(shopCartItem.getPreSellStatus(),1)){
                            date = shopCartItem.getPreSellTime();
                        }
                        Sku sku = checkAndGetSku(shopCartItem.getSkuId(), shopCartItem, skuStocksMap);
                        Product product = checkAndGetProd(shopCartItem.getProdId(), shopCartItem, prodStocksMap);
                        OrderItem orderItem = new OrderItem();
                        orderItem.setShopId(shopId);
                        orderItem.setOrderNumber(orderNumber);
                        orderItem.setSkuId(sku.getSkuId());
                        orderItem.setProdId(sku.getProdId());
                        orderItem.setSkuName(sku.getSkuName());
                        orderItem.setProdCount(shopCartItem.getProdCount());
                        orderItem.setProdName(sku.getProdName());
                        // 保存中英文名称
                        orderItem.setProdNameCn(shopCartItem.getProdNameCn());
                        orderItem.setProdNameEn(shopCartItem.getProdNameEn());
                        orderItem.setPic(StrUtil.isBlank(sku.getPic()) ? product.getPic() : sku.getPic());
                        orderItem.setPrice(shopCartItem.getPrice());
                        orderItem.setUserId(userId);
                        orderItem.setProductTotalAmount(shopCartItem.getProductTotalAmount());
                        orderItem.setRecTime(now);
                        orderItem.setCommSts(0);
                        orderItem.setBasketDate(shopCartItem.getBasketDate());
                        //平台的补贴优惠金额
                        orderItem.setPlatformShareReduce(shopCartItem.getPlatformShareReduce());
                        // 实际订单项支付金额
                        orderItem.setActualTotal(shopCartItem.getActualTotal());
                        // 分摊优惠金额
                        orderItem.setShareReduce(shopCartItem.getShareReduce());
                        orderProdName.append(orderItem.getProdName()).append(",");
                        orderProdNameCn.append(orderItem.getProdNameCn()).append(",");
                        orderProdNameEn.append(orderItem.getProdNameEn()).append(",");
                        //推广员卡号
                        orderItem.setDistributionCardNo(shopCartItem.getDistributionCardNo());
                        //使用积分价格
                        orderItem.setUseScore(shopCartItem.getScorePrice());
                        orderItems.add(orderItem);
                        if (shopCartItem.getBasketId() != null && shopCartItem.getBasketId() != 0) {
                            basketIds.add(shopCartItem.getBasketId());
                        }
                        if (Objects.equals(1,product.getIsCompose())) {
                            SkuRetailParam skuRetailParam = new SkuRetailParam();
                            skuRetailParam.setShopId(shopId);
                            skuRetailParam.setProdId(product.getProdId());
                            skuRetailParam.setSkuId(sku.getSkuId());
                            skuRetailParam.setSkuNums(shopCartItem.getProdCount());
                            skuRetailParam.setSkuName(sku.getProdName());
                            skuRetailParam.setOrderNumber(orderNumber);
                            skuRetailParams.add(skuRetailParam);
                        }
                    }

                }

                //中英文
                orderProdName = new StringBuilder(orderProdName.subSequence(0, Math.min(orderProdName.length() - 1, 100)));
                orderProdNameCn = new StringBuilder(orderProdNameCn.subSequence(0, Math.min(orderProdNameCn.length() - 1, 100)));
                orderProdNameEn = new StringBuilder(orderProdNameEn.subSequence(0, Math.min(orderProdNameEn.length() - 1, 100)));
                if (orderProdName.lastIndexOf(",") == orderProdName.length() - 1) {
                    orderProdName.deleteCharAt(orderProdName.length() - 1);
                }
                if (orderProdNameCn.lastIndexOf(",") == orderProdNameCn.length() - 1) {
                    orderProdNameCn.deleteCharAt(orderProdNameCn.length() - 1);
                }
                if (orderProdNameEn.lastIndexOf(",") == orderProdNameEn.length() - 1) {
                    orderProdNameEn.deleteCharAt(orderProdNameEn.length() - 1);
                }


                // 订单信息
                com.yami.shop.bean.model.Order order = new com.yami.shop.bean.model.Order();

                order.setShopId(shopId);
                order.setOrderNumber(orderNumber);
                // 订单商品名称
                order.setProdName(orderProdName.toString());
                order.setProdNameCn(orderProdNameCn.toString());
                order.setProdNameEn(orderProdNameEn.toString());
                // 用户id
                order.setUserId(userId);
                // 商品总额
                order.setTotal(shopCartOrderDto.getTotal());
                // 实际总额
                order.setActualTotal(shopCartOrderDto.getActualTotal());
                order.setStatus(OrderStatus.UNPAY.value());
                order.setUpdateTime(now);
                order.setCreateTime(now);
                order.setIsPayed(0);
                order.setDeleteStatus(0);
                order.setProductNums(shopCartOrderDto.getTotalCount());
                order.setReduceAmount(shopCartOrderDto.getShopReduce());
                order.setFreightAmount(shopCartOrderDto.getTransfee());
                order.setRemarks(shopCartOrderDto.getRemarks());
                order.setOrderType(OrderType.ORDINARY.value());
                order.setPlatformAmount(shopCartOrderDto.getPlatformAmount());
                order.setOrderItems(orderItems);
                order.setScore(shopCartOrderDto.getUseScore());
                order.setDvyType(mergerOrder.getDvyType());
                order.setDvyId(mergerOrder.getStationId());
                order.setFreeTransfee(shopCartOrderDto.getFreeTransfee());
                // 预售
                order.setPreSaleTime(date);
                event.getOrders().add(order);
                // 插入订单结算表
                OrderSettlement orderSettlement = new OrderSettlement();
                orderSettlement.setUserId(userId);
                orderSettlement.setIsClearing(0);
                orderSettlement.setCreateTime(now);
                orderSettlement.setOrderNumber(orderNumber);
                orderSettlement.setPayAmount(order.getActualTotal());
                orderSettlement.setPayStatus(0);
                orderSettlement.setVersion(0);
                orderSettlement.setPayScore(0);
                //如果用使用积分，结算表将积分价格插入
                if(mergerOrder.getIsScorePay() != null && mergerOrder.getIsScorePay() == 1){
                    orderSettlement.setPayScore(shopCartOrderDto.getUseScore());
                }
                orderSettlementMapper.insert(orderSettlement);
            }
        }

        // 删除购物车的商品信息
        if (!basketIds.isEmpty()) {
            basketMapper.deleteShopCartItemsByBasketIds(userId, basketIds);
        }


        // 更新sku库存
        skuStocksMap.forEach((key, sku) -> {
            if (skuMapper.updateStocks(sku) == 0) {
                skuService.removeSkuCacheBySkuIdAndLang(sku.getSkuId(),sku.getProdId(),LanguageEnum.LANGUAGE_ZH_CN.getLang());
                skuService.removeSkuCacheBySkuIdAndLang(sku.getSkuId(),sku.getProdId(),LanguageEnum.LANGUAGE_EN.getLang());
                productService.removeProdCacheByProdId(sku.getProdId(),LanguageEnum.LANGUAGE_ZH_CN.getLang());
                productService.removeProdCacheByProdId(sku.getProdId(),LanguageEnum.LANGUAGE_EN.getLang());
                // 商品库存不足
                String prodMsg = I18nMessage.getMessage("yami.product");
                String msg = I18nMessage.getMessage("yami.insufficient.inventory");
                throw new YamiShopBindException(prodMsg+"[" + sku.getProdName() + "]"+msg);
            }
        });

        // 更新商品库存
        prodStocksMap.forEach((prodId, prod) -> {

            if (productMapper.updateStocks(prod) == 0) {
                productService.removeProdCacheByProdId(prodId,LanguageEnum.LANGUAGE_ZH_CN.getLang());
                productService.removeProdCacheByProdId(prodId,LanguageEnum.LANGUAGE_EN.getLang());
                // 商品库存不足
                String prodMsg = I18nMessage.getMessage("yami.product");
                String msg = I18nMessage.getMessage("yami.insufficient.inventory");
                throw new YamiShopBindException(prodMsg+"[" + prod.getProdName() + "]"+msg);
            }
        });

        // 更新组合商品的单品库存
        updateComposeProdStocks(skuRetailParams);
    }

    private void updateComposeProdStocks(List<SkuRetailParam> skuRetailParams) {
        if (CollectionUtils.isEmpty(skuRetailParams)) {
            return;
        }
        Date now = new Date();
        List<OrderRetailProdLog> logs = new ArrayList<>();
        skuRetailParams.forEach(i->{
            List<SkuRetail> skuRetails = skuRetailService.list(new LambdaQueryWrapper<SkuRetail>()
                    .eq(SkuRetail::getSkuId, i.getSkuId())
                    .eq(SkuRetail::getStatus, 1));
            if (CollectionUtils.isEmpty(skuRetails)) {
                return;
            }
            // 计算单品减少的库存
            skuRetails.forEach(j->{
                Integer retailNums = j.getRetailNums();
                RetailProd retailProd = new RetailProd();
                retailProd.setRetailProdId(j.getRetailProdId());
                BigInteger a = new BigInteger(String.valueOf(i.getSkuNums()));
                BigInteger b = new BigInteger(String.valueOf(retailNums));
                String s = a.multiply(b).toString();
                Integer stocks = Integer.valueOf(s);
                retailProd.setStocks(stocks);
                if (retailProdMapper.updateStocks(retailProd) == 0) {
                    // 商品库存不足
                    String prodMsg = I18nMessage.getMessage("yami.product");
                    String msg = I18nMessage.getMessage("yami.insufficient.inventory");
                    throw new YamiShopBindException(prodMsg+"[" + i.getSkuName() + "]"+msg);
                }
                // 单品库存减少日志，方便回退
                OrderRetailProdLog log = new OrderRetailProdLog();
                log.setShopId(i.getShopId());
                log.setProdId(i.getProdId());
                log.setSkuId(i.getSkuId());
                log.setRetailProdId(j.getRetailProdId());
                log.setOrderNumber(i.getOrderNumber());
                log.setNum(stocks);
                log.setCreateTime(now);
                logs.add(log);
            });
        });
        orderRetailProdLogService.saveBatch(logs);
        // 单品扣除的原因，将所有单品所在的sku 的库存，计算对应减少的数量，并且更新sku的库存，prod的库存同时更新
        List<Long> ids = logs.stream().map(OrderRetailProdLog::getRetailProdId).distinct().collect(Collectors.toList());
        updateRetainProdRelationSkuAndProdStock(skuRetailParams,ids);

    }


    /**
     * @param skuRetailParams 更新的原始数据
     * @param ids 更新的记录
     */
    private void updateRetainProdRelationSkuAndProdStock(List<SkuRetailParam> skuRetailParams, List<Long> ids) {
        // 将所有相关的单品查询出来，然后根据单品的数量，以及sku的组合单品,更新sku的库存，prod的库存
        if (CollectionUtils.isEmpty(ids)){
            return;
        }
        // 获取单品列表
        List<RetailProd> retailProds = retailProdMapper.selectBatchIds(ids);

        List<SkuRetail> skuRetails = skuRetailMapper.getByRetailProdId(ids);
        Map<Long, List<SkuRetail>> listMap = skuRetails.stream().collect(Collectors.groupingBy(SkuRetail::getSkuId));
        List<Sku> skus = new ArrayList<>();
        listMap.forEach((skuId,lists) ->{
            Sku sku = new Sku();
            sku.setSkuId(skuId);
            List<Integer> skuStocks = new ArrayList<>();
            lists.forEach(k->{
                RetailProd retailProd = retailProds.stream().filter(i -> Objects.equals(i.getRetailProdId(), k.getRetailProdId())).findAny().orElse(null);
                skuStocks.add( new Double(Math.floor(Arith.div(retailProd.getStocks(), k.getRetailNums(), 0))).intValue());
               sku.setProdId(k.getProdId());
            });
            Integer changeStocks = Collections.min(skuStocks);
            // 问题在于根据改变的单品查询出关联的sku,应该是当前sku库存的库存大于改变后的库存时，才需要改变库存
            Sku skuDb = skuMapper.selectById(skuId);
            sku.setStocks(skuDb.getStocks());
            if(skuDb.getStocks() > changeStocks) {
                sku.setStocks(changeStocks);
                skuMapper.updateStocksById(sku);
                // 清除缓存
                skuService.removeSkuCacheBySkuIdAndLang(skuId, sku.getProdId(), LanguageEnum.LANGUAGE_ZH_CN.getLang());
                skuService.removeSkuCacheBySkuIdAndLang(skuId, sku.getProdId(), LanguageEnum.LANGUAGE_EN.getLang());
            }
            skus.add(sku);
        });

        Map<Long, List<Sku>> prods = skus.stream().collect(Collectors.groupingBy(Sku::getProdId));
        prods.forEach((prodId,skuList) ->{
            Product product = new Product();
            product.setProdId(prodId);
            Integer sum = skuList.stream().collect(Collectors.summingInt(Sku::getStocks));
            product.setTotalStocks(sum);
            productMapper.updateStocksById(product);
            productService.removeProdCacheByProdId(prodId,LanguageEnum.LANGUAGE_ZH_CN.getLang());
            productService.removeProdCacheByProdId(prodId,LanguageEnum.LANGUAGE_EN.getLang());
        });
    }

    @SuppressWarnings({"Duplicates"})
    private Product checkAndGetProd(Long prodId, ShopCartItemDto shopCartItem, Map<Long, Product> prodStocksMap) {
        Product product = productService.getProductByProdId(prodId, I18nMessage.getDbLang());
        if (product == null) {
            // 购物车包含无法识别的商品
            throw new YamiShopBindException("yami.contains.unrecognized.items");
        }

        if (product.getStatus() != 1) {
            String message = I18nMessage.getMessage("yami.product");
            String takeOff = I18nMessage.getMessage("yami.shopCart.take.off");
            // 商品已下架
            throw new YamiShopBindException(message+"[" + product.getProdName() + "]"+takeOff);
        }

        // 商品需要改变的库存
        Product mapProduct = prodStocksMap.get(prodId);

        if (mapProduct == null) {
            mapProduct = new Product();
            mapProduct.setTotalStocks(0);
            mapProduct.setProdId(prodId);
            mapProduct.setProdName(product.getProdName());

        }

        if (product.getTotalStocks() != -1) {
            mapProduct.setTotalStocks(mapProduct.getTotalStocks() + shopCartItem.getProdCount());
            prodStocksMap.put(product.getProdId(), mapProduct);
        }

        // -1为无限库存
        if (product.getTotalStocks() != -1 && mapProduct.getTotalStocks() > product.getTotalStocks()) {
            // 商品库存不足
            String prodMsg = I18nMessage.getMessage("yami.product");
            String msg = I18nMessage.getMessage("yami.insufficient.inventory");
            throw new YamiShopBindException(prodMsg+"[" + product.getProdName() + "]"+msg);
        }

        return product;
    }

    @SuppressWarnings({"Duplicates"})
    private Sku checkAndGetSku(Long skuId, ShopCartItemDto shopCartItem, Map<Long, Sku> skuStocksMap) {
        // 获取sku信息
        Sku sku = skuService.getSkuBySkuId(skuId, I18nMessage.getDbLang());
        if (sku == null) {
            // 购物车包含无法识别的商品
            throw new YamiShopBindException("yami.contains.unrecognized.items");
        }

        if (sku.getStatus() != 1) {
            // 商品已下架
            String message = I18nMessage.getMessage("yami.product");
            String takeOff = I18nMessage.getMessage("yami.shopCart.take.off");
            throw new YamiShopBindException(message+"[" + sku.getProdName() + "]"+takeOff);
        }
        // -1为无限库存
        if (sku.getStocks() != -1 && shopCartItem.getProdCount() > sku.getStocks()) {
            // 商品库存不足
            String prodMsg = I18nMessage.getMessage("yami.product");
            String msg = I18nMessage.getMessage("yami.insufficient.inventory");
            throw new YamiShopBindException(prodMsg+"[" + sku.getProdName() + "]"+msg);
        }

        if (sku.getStocks() != -1) {
            Sku mapSku = new Sku();
            mapSku.setProdId(sku.getProdId());
            // 这里的库存是改变的库存
            mapSku.setStocks(shopCartItem.getProdCount());
            mapSku.setSkuId(sku.getSkuId());
            mapSku.setProdName(sku.getProdName());
            skuStocksMap.put(sku.getSkuId(), mapSku);
        }
        return sku;
    }


}
